/**
 * OSAmI: Open Source Ambient Intelligence
 * Copyright (C) 2010 UJF.
 * Contact: osami-general@osami-commons.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 */

package org.osami.gateway.mediator.drools;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import fr.liglab.adele.cilia.Data;
import fr.liglab.adele.cilia.framework.IProcessor;
import org.osami.gateway.sensor.data.SenseData;
import org.osami.gateway.type.Temperature;
import org.osgi.service.log.LogService;
import org.ow2.jasmine.rules.api.IDroolsWorkingMemory;
import org.ow2.jasmine.rules.api.IDroolsWorkingMemoryPool;

import static org.osami.gateway.sensor.data.SenseData.DEFAULT_DATA_KEY;

public class MediatorTemperatureDrools implements IProcessor {

    // TODO replace with a global variable.
    private static final String GATEWAY_ID = "B1-163";

    private final String DEFAULT_MEMORY_NAME = "default";

    /**
     * Drools Service, injected by iPOJO.
     */
    private IDroolsWorkingMemory droolmem;

    /**
     * Logger, injected by iPOJO.
     */
    private LogService logger;

    /**
     * Add the Temperature object to the drools working memory.
     */
    public List process(List dataset) {

        // Filter out non temperature data
        for (Iterator iterator = dataset.iterator(); iterator.hasNext();) {
        	Data raw = (Data) iterator.next();
        	SenseData data = (SenseData) raw.getProperty(SenseData.DEFAULT_DATA_KEY);
			if(!"temperature".equals(data.getType())){
				iterator.remove();
			}
		}
        // Group by senseId
        Map<String, List<SenseData>> groups = new HashMap<String, List<SenseData>>();
        while (!dataset.isEmpty()) {
        	String senseId = ((SenseData)((Data) dataset.get(0)).getProperty(SenseData.DEFAULT_DATA_KEY)).getSenseId();
        	List<SenseData> subdataset = new LinkedList<SenseData>();
        	for (Iterator iterator = dataset.iterator(); iterator.hasNext();) {
        		Data raw = (Data) iterator.next();
            	SenseData data = (SenseData) raw.getProperty(SenseData.DEFAULT_DATA_KEY);
				if(senseId.equals(data.getSenseId())){
					subdataset.add(data);
					iterator.remove();
				}
			}
        	groups.put(senseId, subdataset);
        }
        
        // Compute the average for each group
        // TODO check the unit and convert if needed
        List<Temperature> averages = new ArrayList<Temperature>();
        for (String senseId : groups.keySet()) {
            Iterator<SenseData> i = groups.get(senseId).iterator();
            double count = (double) groups.get(senseId).size();
            double average = 0;
            while (i.hasNext()) {
                SenseData data = (SenseData) i.next();
                try {
                    average += data.getValue();
                } catch (NullPointerException ne) {
                    logger.log(LogService.LOG_WARNING, "The property of key: " + DEFAULT_DATA_KEY + " does not exist, bad data", ne);
                } catch (ClassCastException ce) {
                    logger.log(LogService.LOG_WARNING, "The property of key: " + DEFAULT_DATA_KEY + " is not a valid SenseData object, bad data", ce);
                }
        }
         // Add the Temperature average to the Drools memory
            try {
                    average /= count;
                    Temperature temperature = new Temperature(average, GATEWAY_ID);
                    droolmem.insert(temperature);
                    logger.log(LogService.LOG_INFO, "Average temperature has been send to drools: " + count + " temperature collected, average: "
                            + average);
                    averages.add(temperature);
            } catch (Exception e) {
                logger.log(LogService.LOG_ERROR, "An exception has been reached while adding the temperature average to the drools memory.", e);
            }
        }

        // For test purpose
            return null;
    }

    private void bindDroolsMemoryPool(IDroolsWorkingMemoryPool pool) {
        droolmem = pool.get(DEFAULT_MEMORY_NAME);

        if (droolmem == null) {
            throw new RuntimeException("The DroolsWorkingMemory " + DEFAULT_MEMORY_NAME + "cannot be found ! mediator down ");
        }
    }

    private void stop() {
        droolmem = null;
    }

}
